查看原文
其他

Android Studio自定义模板 写页面竟然可以如此轻松

张鸿洋 鸿洋 2019-04-05
1概述
   

上一篇文章,已经初步对Android Studio的模板有了初步的介绍与使用,以及一些开源模板的推荐:



本文将对如何编写Template,进行详细的介绍(以activity摸版为例)。


2模板的文件结构
   

学习编写模板最好的方式呢,就是参考IDE中已经提供的最简单的模板,那么在Android Studio中最简单的activity模板就是:`Empty Activity`了,我们打开该模板文件,首先对文件结构有个直观的了解,如图:



可以看到每个插件对应一个文件夹,文件夹包含


  • template.xml 

  • globals.xml.ftl

  • recipe.xml.ftl

  • root文件夹 存放对应源码的ftl文件,以及资源文件

  • 效果缩略图


下面我们逐一对上述每个文件的作用进行介绍。


2.1 template.xml


打开该文件,发现其主要内容如下:




其中


  • `<template>`中的`name`属性,对应新建`Activity`时显示的名字

  • `<category>`对应New的类别为Activity


剩下的,对应我们AndroidStudio新建`Empty Activity`的界面就非常好理解了,如图:



看到这个界面,大部分属性都应该能才出来了,我们重点看parameter,界面上每一个紫色框出来的部分都对应一个`parameter `,部分属性介绍:


  • id :唯一标识,最终通过该属性的值,获取用户输入值(文本框内容,是否选中)

  • name:界面上的类似label的提示语

  • type : 输入值类型

  • constraints:填写值的约束

  • suggest:建议值,比如填写ActivityName的时候,会给出一个布局文件的建议值。

  • default:默认值

  • help:底部显示的提升语


这个部分对应界面还是非常好理解的,大家可以简单的修改一些字符串,或者添加一个`<parameter>`,重启AS,看看效果。


template.xml的最下面的部分引入了`globals.xml.ftl``recipe.xml.ftl`


这两个我们会详细介绍。


2.2 globals.xml.ftl



通过名称可以猜到它是用于定义一些全局的变量,可以看到其内部有`<global>`标签,分别定义id,type,默认值。


同理,我们可以通过id的值访问到该值,例如:


  • `${hasNoActionBar}`的值为false。


2.3 recipe.xml.ftl



为了介绍,我将该xml中比较重要的几个标签都列出来了:


  • copy :从root中copy文件到我们的目标目录,比如我们的模板Activity需要使用一些图标,那么可能就需要使用copy标签将这些图标拷贝到我们的项目对应文件夹。

  • merge : 合并的意思,比如将我们使用到的strings.xml合并到我们的项目的stirngs.xml中

  • instantiate : 和copy类似,但是可以看到上例试将ftl->java文件的,也就是说中间会通过一个步骤,将ftl中的变量都换成对应的值,那么完整的流程是`ftl->freemarker process -> java`。

  • open:在代码生成后,打开指定的文件,比如我们新建一个Activity后,默认就会将该Activity打开。


在介绍instantiate时,涉及到了freemarker,不可避免的需要对它进行简单的介绍。


目前我们已经基本了解了一个模板其内部的文件结构了,以及每个文件大致包含的东西,我们简单做个总结:


  • template 中parameter标签,主要用于提供参数

  • global.xml.ftl 主要用于设置一些全局参数

  • recipe.xml.ftl 主要用于生成我们实际需要的代码,资源文件等;例如:利用参数+MainActivity.java.ftl -> MainActivity.java;其实就是利用参数将ftl中的变量进行替换。


那么整体的关系类似下图:


图片取自:http://www.slideshare.net/murphonic/custom-android-code-templates-15537501


3简单的freemarker语法
   

上面我们已经基本了解模板生成的大致的流程以及涉及到的文件,大致了解了我们生成的源码或者xml文件,需要经过:


  • `ftl->freemarker process->java/xml`


这样的流程,那么我们必须对freemarker有个简单的了解。


  • 看一个非常简单的例子


比如我们有个变量user=zhy; 有个ftl文件内容:helloL${user} 最后经过freemarker的输出结果即为 hello:zhy


  • if语法


<#if generateLayout>    //生成layout文件 </#if>


看一眼就知道大概的意思了~有一定的编程经验,即使不知道这个叫freemarker,对于这些简单的语法还是能看懂的。


我们最后以Empty Activity模板的中的SimpleActivity为例:


`root/src/app_package/SimpleActivity.java.ftl`



可以看到其内部包含很多变量,这些变量的值一般来源于用户输入和global.xml.ftl中预定义的值,经过recipe.xml.ftl中instantiate标签的处理,将变量换成实际的值,即可在我们的项目的指定位置,得到我们期望的Activity。


流程大致可用下图说明:



图片取自:http://www.slideshare.net/murphonic/custom-android-code-templates-15537501


看到这,最起码理解了,当我们选择创建不同的Activity类型,最终得到的不同的效果其中的原理原来在这。


4具体的模板实例
   

了解了基本的理论之后,下面我们可以通过一个实例来将上面的知识点整合。


我们编写一个Activity模板叫做:`ViewPagerWithTabActivity`,用于创建一个携带TabLayout的ViewPager,效果如下:



当我们点击New->Activity->ViewPagerWithTabActivity 就可能完成上面的Activity的创建,而避免了编写布局文件,引入design库,以及一些简单的编码。


是不是感觉还是不错的,大家可以针对自己的需求,按照规范的格式随意定制模板。


建议大家copy一个现有的模板,在其基础上修改即可,比如本例是在Empty Activity基础之上修改的。


下面我们看上例的具体的实现。


4.1template.xml的编写


通过上面的学习我们知道template.xml中可以定义我们创建面板的控件布局等,本例我们创建Activity的界面如下:




对应的template.xml如下:



经过前面的学习应该很好理解,每个parameter对应界面上的一个控件,控件的这个id最终可以得到用户输入值,后面会用于渲染ftl文件。


4.2 用到的类


本例中最终需要生成Fragment和Activity,也就是说对应会有两个ftl文件分别用于最终生成这两个类。


  • `root/src/app_package/MainActivity.java.ftl`




注意不是.java文件而是.ftl文件,可以看到上面的代码基础上和Java代码没什么区别,实际上就是Java代码,把可变的部分都换成了`${变量名}`的方式而已。


例如:类名是用户填写的,我们就使用`${activityClass}`替代,其他同理。


  • `root/src/app_package/SimpleFragment.java.ftl`



这个类更简单,除了package是动态的,其他都写好了,主要用于作为ViewPager的Fragment Item.


4.3 用到的布局文件


  • `root/res/layout/activity_main.xml.ftl`



发现和我们真正编写的Activity并无多大区别。


看完用到的类和布局文件的ftl,大家心里应该有个底了,这模板几乎就和我们平时写的Java类一样,只是根据用户在新建Actiivty界面所输入的参数进行替换一些变量或者做一些简单的操作而已。


4.4 recipe.xml.ftl的编写


除了template.xml还有globals.xml.ftl和recipe.xml.ftl,globals.xml.ftl中基本上没有修改任何内容就不介绍了。


 recipe.xml.ftl中定义的东西比较关键,例如引入依赖ftl->javacopy资源文件合并资源文件等。

 

 内容较长,我们拆开描述。

 

  • recipe.xml.ftl中引入依赖部分



本例依赖v4、v7、和design库,我们需要在这里定义引入;你再也不需要去一个一个区搜索添加了。


  • 你可能会问,这个引入的代码看起来挺复杂,你怎么知道这样写呢?


其实我也不知道怎么写,但是我可以打开IDE自带模板参考参考,看看哪些需要这些依赖,copy过来就好了。


  • recipe.xml.ftl中剩下的内容



可以看到包含多个instantiate标签,该标签很明显是将我们内置的ftl转化为当前项目有中的java类。


上例,转化了`${activityClass}.java``fragment/SimpleFragment.java`还有我们的`/layout/${activityLayoutName}.xml`


剩下是两个open标签,主要就是用于新建完成后,自动打开该文件。


本例新建完成后,Activity和其对应的布局文件都会自动打开。


恩,这里没用到`merge`标签,不过也很简单,假设你fragment上显示的文本,你可以定义到一个strings.xml里面,最后你需要将这个strings.xml合并到当前项目的strings.xml就可以使用merge标签(内置模板很多用了merge标签,参考下,抄一抄就搞定了)。


ok,到这,我们整个模板的编写介绍就结束了。


5总结
   

本文我们首先详细介绍了一个模板文件夹下各个文件以及其内部的标签的作用,然后通过一个具体的实例,来演示如何编写一个activity模板。


如果你看的足够仔细,再花点时间动手,根据需求编写几个模板应该是不成问题的。


当然,文中一些细节并没有谈到,对于这些不要担心,你有什么需求,你就想哪个内置的模板好像有类似的需求,看它的实现,copy它的相关代码改一改就好了,没有必要去被各种文件的编写,这种东西copy修改就好了。


测试过程中,需要重启Android Studio,如果有问题,记得查看Event Log面板的信息。


--欢迎长按或者扫码关注,不要错过每一篇干货--

-本公众号支持投稿,直接投递md文件或者链接至我邮箱-






    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存